"""
认证路由
创建时间：2025-09-12
作者：开发团队
目的：处理用户认证相关API路由
"""

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.orm import Session
from datetime import datetime, timedelta, timezone


from jose.exceptions import JWTError
from ..core.database import get_db
from ..core.security import verify_password, create_access_token, decode_access_token
from ..services.auth_service import get_user_by_username, update_last_login
from ..models.user import User
from ..schemas.user import UserResponse, LoginRequest, LoginResponse
from ..utils.logger import get_logger

# 创建路由实例
router = APIRouter(prefix="/auth", tags=["认证"])

# JWT过期时间
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 8  # 8天

# OAuth2密码流
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")

# 获取日志记录器
logger = get_logger(__name__)

# 依赖项：获取当前用户
async def get_current_user(
    token: str = Depends(oauth2_scheme),
    db: Session = Depends(get_db)
):
    """
    获取当前用户依赖项
    :param token: JWT令牌
    :param db: 数据库会话
    :return: 用户对象
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="无法验证凭据",
        headers={"WWW-Authenticate": "Bearer"},
    )
    
    try:
        payload = decode_access_token(token)
        if payload is None:
            raise credentials_exception
        username = payload.get("sub")
        if username is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    
    user = get_user_by_username(db, username=str(username))
    if user is None:
        raise credentials_exception
    
    return user


# 依赖项：获取当前活跃用户
async def get_current_active_user(
    current_user: User = Depends(get_current_user)
):
    """
    获取当前活跃用户依赖项
    :param current_user: 当前用户对象
    :return: 活跃用户对象
    """
    if str(current_user.status) != "active":
        raise HTTPException(status_code=400, detail="账户已被禁用")
    return current_user


@router.post("/login", response_model=LoginResponse)
async def login(
    login_request: LoginRequest,
    db: Session = Depends(get_db)
):
    """
    用户登录
    :param login_request: 登录请求数据
    :param db: 数据库会话
    :return: 登录响应
    """
    # 添加调试日志
    logger.info(f"登录请求: username={login_request.username}, password_length={len(login_request.password)}")
    
    # 调试：检查数据库文件
    from ..core.config import get_config
    config = get_config()
    logger.info(f"当前数据库URL: {config.DATABASE_URL}")
    
    # 调试：列出所有用户
    all_users = db.query(User).all()
    logger.info(f"数据库中的所有用户: {[u.username for u in all_users]}")
    
    # 验证用户
    user = get_user_by_username(db, login_request.username)
    logger.info(f"查询用户结果: {user is not None}")
    
    if not user:
        logger.info("用户不存在")
        return LoginResponse(
            code=401,
            message="用户名或密码错误",
            data=None,
            error="用户名或密码错误",
            timestamp=datetime.now(timezone.utc)
        )
    
    logger.info(f"用户信息: id={user.id}, username={user.username}, role={user.role}, status={user.status}")
    logger.info(f"密码哈希: {user.password_hash}")
    logger.info(f"请求密码长度: {len(login_request.password)}")
    
    # 验证密码
    password_valid = verify_password(login_request.password, str(user.password_hash))
    logger.info(f"密码验证结果: {password_valid}")
    
    if not password_valid:
        logger.info("用户名或密码错误")
        return LoginResponse(
            code=401,
            message="用户名或密码错误",
            data=None,
            error="用户名或密码错误",
            timestamp=datetime.now(timezone.utc)
        )
    
    # 检查账户状态
    if str(user.status) != "active":
        logger.info("账户已被禁用")
        return LoginResponse(
            code=403,
            message="账户已被禁用",
            data=None,
            error="账户已被禁用",
            timestamp=datetime.now(timezone.utc)
        )
    
    # 更新最后登录时间
    update_last_login(db, int(str(user.id)), datetime.now(timezone.utc))
    
    # 创建访问令牌
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": str(user.username), "user_id": int(str(user.id)), "role": str(user.role)},
        expires_delta=access_token_expires
    )
    
    # 获取用户字段值，使用getattr安全获取属性
    user_id = int(str(getattr(user, 'id')))
    user_username = str(getattr(user, 'username'))
    user_name = str(getattr(user, 'name'))
    user_role = str(getattr(user, 'role'))
    user_phone = str(getattr(user, 'phone')) if getattr(user, 'phone') else None
    user_campus_id = int(str(getattr(user, 'campus_id'))) if getattr(user, 'campus_id') else None
    user_status = str(getattr(user, 'status'))
    user_last_login = getattr(user, 'last_login')
    user_created_at = getattr(user, 'created_at')
    # 安全地获取campus_name
    user_campus = getattr(user, 'campus')
    user_campus_name = str(getattr(user_campus, 'name')) if user_campus else None
    
    # 构造用户响应数据，确保包含API契约中定义的所有字段
    user_response = UserResponse(
        id=user_id,
        username=user_username,
        name=user_name,
        role=user_role,
        phone=user_phone,
        campus_id=user_campus_id,
        status=user_status,
        last_login=user_last_login,
        created_at=user_created_at,
        campus_name=user_campus_name,
        permissions=[]  # 根据用户角色设置权限
    )
    
    # 根据用户角色设置权限
    if user_role == "guard":
        user_response.permissions = ["verification.scan", "verification.submit"]
    elif user_role == "admin":
        user_response.permissions = ["admin.manage", "statistics.view"]
    elif user_role == "superadmin":
        user_response.permissions = ["superadmin.manage", "system.config"]
    
    # 返回统一格式响应
    logger.info("登录成功")
    return LoginResponse(
        code=200,
        message="success",
        data={
            "token": access_token,
            "user": user_response
        },
        timestamp=datetime.now(timezone.utc)
    )


@router.post("/logout")
async def logout():
    """
    用户登出
    :return: 登出成功确认
    """
    # 在JWT模式下，登出主要是客户端清除令牌
    return {
        "code": 200,
        "message": "success",
        "timestamp": datetime.now(timezone.utc)
    }


@router.get("/profile")
async def read_users_me(
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> dict[str, int | str | dict[str, int | str | list[str] | None] | datetime] | dict[str, int | str | datetime | None]:
    """
    获取当前用户信息
    :param current_user: 当前用户对象
    :param db: 数据库会话
    :return: 用户信息响应
    """
    try:
        # 获取用户字段值，使用getattr安全获取属性
        user_id = int(str(getattr(current_user, 'id')))
        user_username = str(getattr(current_user, 'username'))
        user_name = str(getattr(current_user, 'name'))
        user_role = str(getattr(current_user, 'role'))
        user_phone = str(getattr(current_user, 'phone')) if getattr(current_user, 'phone') else None
        user_campus_id = int(str(getattr(current_user, 'campus_id'))) if getattr(current_user, 'campus_id') else None

        # 安全地获取campus_name
        user_campus = getattr(current_user, 'campus')
        user_campus_name = str(getattr(user_campus, 'name')) if user_campus else None
        
        # 构造用户响应数据，确保包含API契约中定义的所有字段
        user_response: dict[str, int | str | list[str] | None] = {
            "id": user_id,
            "username": user_username,
            "name": user_name,
            "role": user_role,
            "phone": user_phone,
            "campus_id": user_campus_id,
            "campus_name": user_campus_name,
            "permissions": []  # 根据用户角色设置权限
        }
        
        # 根据用户角色设置权限
        if user_role == "guard":
            user_response["permissions"] = ["verification.scan", "verification.submit"]
        elif user_role == "admin":
            user_response["permissions"] = ["admin.manage", "statistics.view"]
        elif user_role == "superadmin":
            user_response["permissions"] = ["superadmin.manage", "system.config"]
        
        # 返回统一格式响应
        return {
            "code": 200,
            "message": "success",
            "data": user_response,
            "timestamp": datetime.now(timezone.utc)
        }
    except Exception as e:
        return {
            "code": 500,
            "message": "服务器内部错误",
            "data": None,
            "error": str(e),
            "timestamp": datetime.now(timezone.utc)
        }